#include "trie.hpp"
#include <string>
#include <vector>
#include <iterator>
#include <iostream>
using namespace std;

template<typename elem_t, typename data_t>
void print_trie(const trie<elem_t, data_t>& t) {
  cout << "listing START" << endl;
  for (typename trie<elem_t, data_t>::const_iterator i = t.begin(); i != t.end(); ++i) {
    cout << *i << endl;
  }
  cout << "listing END" << endl;
}

template<typename elem_t, typename data_t>
void print_subtrie(trie<elem_t, data_t>& t, string s) {
  const trie<elem_t, data_t> st = t.subtrie(s);
  print_trie(st);
}

int main(int argc, const char** argv) {

  // Test with strings from the command line
  
  trie<const char, int> n;
  for (int i = 1; i < argc; ++i) {
    //    (*n).insert(string(argv[i]), i);
    (*n).insert(argv[i], '\0', i);
  }

  cout << "listing START" << endl;
  for (trie<const char, int>::iterator i = n.begin(); i != n.end(); ++i) {
    cout << *i << endl;
  }
  cout << "listing END" << endl;

  /*
  cout << "with prefix 'a': ";
  trie<const char, int> na(*n > 'a');
  for (trie<const char, int>::iterator i = na.begin(); i != na.end(); ++i) {
    cout << *i << " ";
  }
  cout << endl;
  */
  
  // Test find and "random access" (operator[])
  
  cout << "listing START" << endl;
  for (int i = argc-1; i >= 0; --i) {
    string s(argv[i]);
    cout << s << "\t";
    trie<const char, int>::iterator j = (*n).find(s);
    if (j != n.end()) {
      cout << *j << endl;
    } else {
      cout << "n/a" << endl;
    }
    cout << "\t" << (*n)[s] << endl;
  }
  cout << "listing END" << endl;
  
  trie<const char, int> j(*n > string("ba") > 'a');
  cout << "n > string(\"ba\") > 'a'" << endl;
  cout << "\t" << *j.root() << endl;
  
  // Test arbitrary sequences (vectors)

  int num[] = {1, 2, 3};
  vector<int> v1(num, num+3);
  num[2] = 4;
  vector<int> v2(num, num+3);

  trie<int, vector<int> > vt;
  (*vt).insert(v1, v1);
  (*vt).insert(v2, v2);

  cout << "listing START" << endl;
  for (trie<int, vector<int> >::iterator i = vt.begin(); i != vt.end(); ++i) {
    for (vector<int>::iterator j = i->begin(); j != i->end(); ++j) {
      cout << *j << " ";
    }
    cout << endl;
  }
  cout << "listing END" << endl;

  // Test arrays as sequences
  
  int i1[] = {4,5,6};
  int i2[] = {4,5,7};
  trie<int, int> it;
  (*it).insert(i1+0, i1+3, 15);
  (*it).insert(i2+0, i2+3, 16);
  
  cout << "listing START" << endl;
  for (trie<int, int>::iterator i = it.begin(); i != it.end(); ++i) {
    cout << *i << endl;
  }
  cout << "listing END" << endl;
  

};
